"use strict";

module.exports = core;

// require可以支持加载js，json，node三种后缀的文件
// js:必须得通过module.exports或者exports
// .json:会自己使用json.parse来进行转换然后输出

const userHome = require("user-home");
const dotEnv = require("dotenv"); //获取用户目录的环境变量
const pathExists = require("path-exists").sync; //路径是否存在,sync是同步
const semver = require("semver"); //这个库是用来对比版本号的
const colors = require("colors"); //改变控制台输出的颜色
const commander = require("commander"); //命令注册

const path = require("path");
const pkg = require("../package.json");
const log = require("@hjc-cli-dev/log");
const { getNpmSemverVersion } = require("@hjc-cli-dev/get-npm-info");
const exec = require("@hjc-cli-dev/exec");

const { DEFAULT_CLI_HOME } = require("./const");

const program = new commander.Command();
async function core() {
    try {
        await prepare();
        registerCommander(); //注册命令
    } catch (error) {
        log.error(error);
        if (program.debug) {
            console.log(error);
        }
    }
}

async function prepare() {
    checkPkgVersion();
    checkRoot(); //检查root启动
    checkUserHome(); //检查用户主目录是都存在
    //checkInputArgs(); //检查入参开启debug模式
    checkEnv(); //检查环境变量
    await checkGlobal(); //检查版本，提示用户升级
}
async function checkGlobal() {
    // 1.获取到本地的版本号
    // 2.调用npm的api获取到所有的版本号集合
    // 3.提取所有版本号，对比哪些版本号是大于当前版本号的
    // 4.获取到最新的版本号，提示用户更新
    const currentVersion = pkg.version;
    const name = pkg.name;
    const lastVersion = await getNpmSemverVersion(currentVersion, name);
    if (lastVersion && semver.gt(lastVersion, currentVersion)) {
        log.warn(
            "更新提示",
            colors.yellow(`
        请手动更新 ${name},
        当前版本 ${currentVersion}
        最新版本 ${lastVersion}
        更新命令 npm install -g ${name}
        `)
        );
    }
}

function registerCommander() {
    program
        .name(Object.keys(pkg.bin)[0])
        .usage("[commander],<options>")
        .version(pkg.version)
        .option("-d, --debug", "是否开启debug模式", false)
        .option("-tp, --targetPath <targetPath>", "是否指定本地调试路径", "");

    // 注册命令
    program.command("init [projectName]").option("-f,--force", "是否强制初始化项目").action(exec);
    // 开启debug模式
    program.on("option:debug", function () {
        if (program.debug) {
            process.env.LOG_LEVEL = "verbose";
        } else {
            process.env.LOG_LEVEL = "info";
        }
        log.level = process.env.LOG_LEVEL;
        log.verbose("test");
    });

    // 指定targetPath
    program.on("option:targetPath", function () {
        if (
            program.rawArgs[program.rawArgs.length - 1] &&
            program.rawArgs[program.rawArgs.length - 1] !== "--targetPath"
        ) {
            process.env.CLI_TARGET_PATH = arguments[0];
        }
    });
    // 对不存在的命令进行监听
    program.on("command:*", function (data) {
        const allCommands = program.commands.map((cmd) => cmd.name());
        console.log(colors.red(`未知的命令：${data[0]}`));
        if (allCommands.length) {
            console.log(colors.red(`可用命令：${allCommands.join(",")}`));
        }
    });

    program.parse(process.argv);
    // 没有实际的功能的就给用户直接显示帮助文档
    if (program.args && !program.args.length) {
        program.outputHelp();
        console.log(); //打印空行隔开
    }
}

// 检查环境变量的目的是为了生成用户缓存目录
function checkEnv() {
    // .env文件默认在用户主目录是不存在的，需要的可以主动创建，形式类似于hjc=100
    // .env文件可以通过node里面的process.env[对应键值]拿到
    // 就相当于全局变量，很多地方都能拿到
    const dotEnvPath = path.resolve(userHome, ".env");
    if (dotEnvPath) {
        //如果本地创建了这个文件，传入了环境变量
        const config = dotEnv.config({
            //直接读取
            path: dotEnvPath,
        });
        if (config.error) {
            createDefaultConfig();
        }
    } else {
        createDefaultConfig(); //否则需要一个默认值代替
    }
    //将默认值写入node的process.env，这样全局都能拿到
    // log.notice("环境变量", process.env.CLI_HOME_PATH);
}

function createDefaultConfig() {
    const cliConfig = {
        home: userHome,
    };
    if (process.env.CLI_HOME) {
        cliConfig["cliHome"] = path.join(userHome, process.env.CLI_HOME);
    } else {
        cliConfig["cliHome"] = path.join(userHome, DEFAULT_CLI_HOME);
    }
    process.env.CLI_HOME_PATH = cliConfig.cliHome;
}

function checkUserHome() {
    //检查用户主目录

    if (!userHome || !pathExists(userHome)) {
        //用户主目录获取不到或者目录路径不存在时报错
        throw new Error(colors.red("当前登录用户主目录不存在！"));
    }
}

function checkRoot() {
    const rootCheck = require("root-check");
    rootCheck();
}
function checkPkgVersion() {
    log.notice("cli", pkg.version);
}
